`timescale 1ns / 1ns

module sim_fifo(

);

localparam DATA_WIDTH = 32;
localparam ADDR_LEN   = 16;
localparam PROGRAM_FULL_SET  = 10;
localparam PROGRAM_FULL_CLR  = 4;
localparam PROGRAM_EMPTY_SET = 1;
localparam PROGRAM_EMPTY_CLR = 5;

reg rd_clk;
reg wr_clk;
reg rd_reset;
reg wr_reset;

reg  [DATA_WIDTH - 1:0 ] wr_data;
reg                      wr_en;
reg                      rd_en;
wire [DATA_WIDTH - 1:0 ] rd_data;

wire wr_full;
wire rd_empty;
wire wr_full_program;
wire rd_empty_program;
reg  test_write_to_full;
reg  test_read_to_empty;

reg [7:0] wr_cnt;

async_fifo # (
    .DATA_WIDTH         (DATA_WIDTH         ),
    .ADDR_LEN           (ADDR_LEN           ),
    .PROGRAM_FULL_SET   (PROGRAM_FULL_SET   ),
    .PROGRAM_FULL_CLR   (PROGRAM_FULL_CLR   ),
    .PROGRAM_EMPTY_SET  (PROGRAM_EMPTY_SET  ),
    .PROGRAM_EMPTY_CLR  (PROGRAM_EMPTY_CLR  )
) u_fifo_dut
(
    .rd_clk             (rd_clk),
    .rd_reset           (rd_reset),

    .wr_clk             (wr_clk),
    .wr_reset           (wr_reset),

    .wr_en              (wr_en),
    .wr_data            (wr_data),

    .rd_en              (rd_en),
    .rd_data            (rd_data),

    .wr_full            (wr_full),
    .rd_empty           (rd_empty),
    .wr_full_program    (wr_full_program),
    .rd_empty_program   (rd_empty_program)   
);

always #2 wr_clk <= ~ wr_clk;
always #5 rd_clk <= ~ rd_clk;

initial begin
    #0  begin wr_clk <= 0; rd_clk <= 0; wr_reset <= 1; rd_reset <= 1;test_write_to_full <= 0; test_read_to_empty <= 0;end
    #50 begin wr_reset <= 0; rd_reset <= 0;end
    #100 begin test_write_to_full <= 1;test_read_to_empty <= 0;end
    #2000 begin test_read_to_empty <= 1;test_write_to_full <= 0;end
    #5000 $finish();
end

always@(posedge wr_clk) begin
    if(wr_reset) begin
        wr_data <= 0;
        wr_cnt  <= 0;
        wr_en   <= 0;
    end
    else if(test_write_to_full && (~wr_full)) begin
        wr_data <= {wr_cnt,wr_cnt,wr_cnt,wr_cnt};
        wr_cnt  <= wr_cnt + 1;
        wr_en   <= 1;
    end
    else if(test_read_to_empty) begin
        wr_data <= 0;
        wr_cnt  <= 0;
        wr_en   <= 0;
    end
    else begin
        wr_data <= 0;
        wr_cnt  <= 0;
        wr_en   <= 0;
    end
end

always@(posedge rd_clk) begin
    if(rd_reset) begin
        rd_en <= 0;
    end
    else if(test_write_to_full) begin
        rd_en <= 1;
    end
    else if(test_read_to_empty && (~rd_empty)) begin
        rd_en <= 1;
    end
    else begin
        rd_en <= 0;
    end
end

initial
begin            
    $dumpfile("wave.vcd");        //生成的vcd文件名称
    $dumpvars(0, sim_fifo);    //tb模块名称
end

endmodule
